Implement P0392r0. Integrate filesystem::path and string_view. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@276511 91177308-0d34-0410-b5e6-96231b3b80d8 
diff --git a/include/experimental/filesystem b/include/experimental/filesystem index 7de93fd..0075ad2 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem 
@@ -228,7 +228,7 @@  #include <system_error>  #include <utility>  #include <iomanip> // for quoted -#include <experimental/string_view> +#include <string_view>    #include <__debug>   @@ -498,6 +498,21 @@  }  };   + +template <class _ECharT, class _Traits> +struct __is_pathable_string<basic_string_view<_ECharT, _Traits>, + _Void<typename __can_convert_char<_ECharT>::__char_type>> +: public __can_convert_char<_ECharT> +{ + using _Str = basic_string_view<_ECharT, _Traits>; + using _Base = __can_convert_char<_ECharT>; + static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } + static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); } + static _ECharT __first_or_null(_Str const& __s) { + return __s.empty() ? _ECharT{} : __s[0]; + } +}; +  template <class _Source,  class _DS = typename decay<_Source>::type,  class _UnqualPtrType = typename remove_const< @@ -642,6 +657,7 @@  public:  typedef char value_type;  typedef basic_string<value_type> string_type; + typedef _VSTD::string_view __string_view;  static _LIBCPP_CONSTEXPR value_type preferred_separator = '/';    // constructors and destructor @@ -788,6 +804,12 @@  }    _LIBCPP_INLINE_VISIBILITY + path& operator+=(__string_view __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY  path& operator+=(const value_type* __x) {  __pn_ += __x;  return *this; @@ -799,7 +821,6 @@  return *this;  }   -  template <class _ECharT>  typename enable_if<__can_convert_char<_ECharT>::value, path&>::type  operator+=(_ECharT __x) @@ -896,30 +917,31 @@  std::u32string generic_u32string() const { return string<char32_t>(); }    private: - _LIBCPP_FUNC_VIS int __compare(const value_type*) const; - _LIBCPP_FUNC_VIS string_view __root_name() const; - _LIBCPP_FUNC_VIS string_view __root_directory() const; - _LIBCPP_FUNC_VIS string_view __relative_path() const; - _LIBCPP_FUNC_VIS string_view __parent_path() const; - _LIBCPP_FUNC_VIS string_view __filename() const; - _LIBCPP_FUNC_VIS string_view __stem() const; - _LIBCPP_FUNC_VIS string_view __extension() const; + _LIBCPP_FUNC_VIS int __compare(__string_view) const; + _LIBCPP_FUNC_VIS __string_view __root_name() const; + _LIBCPP_FUNC_VIS __string_view __root_directory() const; + _LIBCPP_FUNC_VIS __string_view __relative_path() const; + _LIBCPP_FUNC_VIS __string_view __parent_path() const; + _LIBCPP_FUNC_VIS __string_view __filename() const; + _LIBCPP_FUNC_VIS __string_view __stem() const; + _LIBCPP_FUNC_VIS __string_view __extension() const;    public:  // compare - _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const _NOEXCEPT { return __compare(__p.c_str());} - _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const { return __compare(__s.c_str()); } + _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const _NOEXCEPT { return __compare(__p.__pn_);} + _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const { return __compare(__s); } + _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const { return __compare(__s); }  _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const { return __compare(__s); }    // decomposition - _LIBCPP_INLINE_VISIBILITY path root_name() const { return __root_name().to_string(); } - _LIBCPP_INLINE_VISIBILITY path root_directory() const { return __root_directory().to_string(); } - _LIBCPP_INLINE_VISIBILITY path root_path() const { return root_name().append(__root_directory().to_string()); } - _LIBCPP_INLINE_VISIBILITY path relative_path() const { return __relative_path().to_string(); } - _LIBCPP_INLINE_VISIBILITY path parent_path() const { return __parent_path().to_string(); } - _LIBCPP_INLINE_VISIBILITY path filename() const { return __filename().to_string(); } - _LIBCPP_INLINE_VISIBILITY path stem() const { return __stem().to_string();} - _LIBCPP_INLINE_VISIBILITY path extension() const { return __extension().to_string(); } + _LIBCPP_INLINE_VISIBILITY path root_name() const { return string_type(__root_name()); } + _LIBCPP_INLINE_VISIBILITY path root_directory() const { return string_type(__root_directory()); } + _LIBCPP_INLINE_VISIBILITY path root_path() const { return root_name().append(string_type(__root_directory())); } + _LIBCPP_INLINE_VISIBILITY path relative_path() const { return string_type(__relative_path()); } + _LIBCPP_INLINE_VISIBILITY path parent_path() const { return string_type(__parent_path()); } + _LIBCPP_INLINE_VISIBILITY path filename() const { return string_type(__filename()); } + _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem());} + _LIBCPP_INLINE_VISIBILITY path extension() const { return string_type(__extension()); }    // query  _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT { return __pn_.empty(); } @@ -945,7 +967,7 @@    private:  inline _LIBCPP_INLINE_VISIBILITY - path& __assign_view(string_view const& __s) noexcept { __pn_ = __s.to_string(); return *this; } + path& __assign_view(__string_view const& __s) noexcept { __pn_ = string_type(__s); return *this; }  string_type __pn_;  };   
diff --git a/src/experimental/filesystem/path.cpp b/src/experimental/filesystem/path.cpp index 38c4498..22ad23b 100644 --- a/src/experimental/filesystem/path.cpp +++ b/src/experimental/filesystem/path.cpp 
@@ -7,20 +7,21 @@  //  //===----------------------------------------------------------------------===//  #include "experimental/filesystem" -#include "experimental/string_view" +#include "string_view"  #include "utility"    _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM    _LIBCPP_CONSTEXPR path::value_type path::preferred_separator;   + +using string_view_t = path::__string_view; +  namespace { namespace parser  {   -using string_type = string_view;  using value_type = path::value_type; - -using string_view_pair = pair<string_view, string_view>; +using string_view_pair = pair<string_view_t, string_view_t>;    // status reporting  constexpr size_t npos = static_cast<size_t>(-1); @@ -33,43 +34,43 @@  constexpr value_type const * dot = ".";    // forward // -bool is_separator(string_type const &, size_t); -bool is_root_name(const string_type&, size_t); -bool is_root_directory(string_type const &, size_t); -bool is_trailing_separator(string_type const &, size_t); +bool is_separator(string_view_t const &, size_t); +bool is_root_name(const string_view_t&, size_t); +bool is_root_directory(string_view_t const &, size_t); +bool is_trailing_separator(string_view_t const &, size_t);   -size_t start_of(string_type const &, size_t); -size_t end_of(string_type const &, size_t); +size_t start_of(string_view_t const &, size_t); +size_t end_of(string_view_t const &, size_t);   -size_t root_name_start(const string_type& s); -size_t root_name_end(const string_type&); +size_t root_name_start(const string_view_t& s); +size_t root_name_end(const string_view_t&);   -size_t root_directory_start(string_type const &); -size_t root_directory_end(string_type const &); +size_t root_directory_start(string_view_t const &); +size_t root_directory_end(string_view_t const &);   -string_view_pair separate_filename(string_type const &); -string_view extract_raw(string_type const &, size_t); -string_view extract_preferred(string_type const &, size_t); +string_view_pair separate_filename(string_view_t const &); +string_view extract_raw(string_view_t const &, size_t); +string_view extract_preferred(string_view_t const &, size_t);   -inline bool is_separator(const string_type& s, size_t pos) { +inline bool is_separator(const string_view_t& s, size_t pos) {  return (pos < s.size() && s[pos] == preferred_separator);  }   -inline bool is_root_name(const string_type& s, size_t pos) { +inline bool is_root_name(const string_view_t& s, size_t pos) {  return good(pos) && pos == 0 ? root_name_start(s) == pos : false;  }   -inline bool is_root_directory(const string_type& s, size_t pos) { +inline bool is_root_directory(const string_view_t& s, size_t pos) {  return good(pos) ? root_directory_start(s) == pos : false;  }   -inline bool is_trailing_separator(const string_type& s, size_t pos) { +inline bool is_trailing_separator(const string_view_t& s, size_t pos) {  return (pos < s.size() && is_separator(s, pos) &&  end_of(s, pos) == s.size()-1 &&  !is_root_directory(s, pos) && !is_root_name(s, pos));  }   -size_t start_of(const string_type& s, size_t pos) { +size_t start_of(const string_view_t& s, size_t pos) {  if (pos >= s.size()) return npos;  bool in_sep = (s[pos] == preferred_separator);  while (pos - 1 < s.size() && @@ -81,7 +82,7 @@  return pos;  }   -size_t end_of(const string_type& s, size_t pos) { +size_t end_of(const string_view_t& s, size_t pos) {  if (pos >= s.size()) return npos;  // special case for root name  if (pos == 0 && is_root_name(s, pos)) return root_name_end(s); @@ -91,11 +92,11 @@  return pos;  }   -inline size_t root_name_start(const string_type& s) { +inline size_t root_name_start(const string_view_t& s) {  return good(root_name_end(s)) ? 0 : npos;  }   -size_t root_name_end(const string_type& s) { +size_t root_name_end(const string_view_t& s) {  if (s.size() < 2 || s[0] != preferred_separator  || s[1] != preferred_separator) {  return npos; @@ -113,14 +114,14 @@  return index;  }   -size_t root_directory_start(const string_type& s) { +size_t root_directory_start(const string_view_t& s) {  size_t e = root_name_end(s);  if (!good(e))  return is_separator(s, 0) ? 0 : npos;  return is_separator(s, e + 1) ? e + 1 : npos;  }   -size_t root_directory_end(const string_type& s) { +size_t root_directory_end(const string_view_t& s) {  size_t st = root_directory_start(s);  if (!good(st)) return npos;  size_t index = st; @@ -129,20 +130,20 @@  return index;  }   -string_view_pair separate_filename(string_type const & s) { +string_view_pair separate_filename(string_view_t const & s) {  if (s == "." || s == ".." || s.empty()) return string_view_pair{s, ""};  auto pos = s.find_last_of('.'); - if (pos == string_type::npos) return string_view_pair{s, string_view{}}; + if (pos == string_view_t::npos) return string_view_pair{s, string_view{}};  return string_view_pair{s.substr(0, pos), s.substr(pos)};  }   -inline string_view extract_raw(const string_type& s, size_t pos) { +inline string_view extract_raw(const string_view_t& s, size_t pos) {  size_t end_i = end_of(s, pos);  if (!good(end_i)) return string_view{};  return string_view(s).substr(pos, end_i - pos + 1);  }   -string_view extract_preferred(const string_type& s, size_t pos) { +string_view extract_preferred(const string_view_t& s, size_t pos) {  string_view raw = extract_raw(s, pos);  if (raw.empty())  return raw; @@ -260,14 +261,14 @@  ///////////////////////////////////////////////////////////////////////////////  // path.decompose   -string_view path::__root_name() const +string_view_t path::__root_name() const  {  return parser::is_root_name(__pn_, 0)  ? parser::extract_preferred(__pn_, 0) - : string_view{}; + : string_view_t{};  }   -string_view path::__root_directory() const +string_view_t path::__root_directory() const  {  auto start_i = parser::root_directory_start(__pn_);  if(!parser::good(start_i)) { @@ -276,49 +277,49 @@  return parser::extract_preferred(__pn_, start_i);  }   -string_view path::__relative_path() const +string_view_t path::__relative_path() const  {  if (empty()) { - return {__pn_}; + return __pn_;  }  auto end_i = parser::root_directory_end(__pn_);  if (not parser::good(end_i)) {  end_i = parser::root_name_end(__pn_);  }  if (not parser::good(end_i)) { - return {__pn_}; + return __pn_;  } - return string_view(__pn_).substr(end_i+1); + return string_view_t(__pn_).substr(end_i+1);  }   -string_view path::__parent_path() const +string_view_t path::__parent_path() const  {  if (empty() || pbegin(*this) == --pend(*this)) {  return {};  }  auto end_it = --(--pend(*this));  auto end_i = parser::end_of(__pn_, end_it.__pos_); - return string_view(__pn_).substr(0, end_i+1); + return string_view_t(__pn_).substr(0, end_i+1);  }   -string_view path::__filename() const +string_view_t path::__filename() const  { - return empty() ? string_view{} : *--pend(*this); + return empty() ? string_view_t{} : *--pend(*this);  }   -string_view path::__stem() const +string_view_t path::__stem() const  {  return parser::separate_filename(__filename()).first;  }   -string_view path::__extension() const +string_view_t path::__extension() const  {  return parser::separate_filename(__filename()).second;  }    ////////////////////////////////////////////////////////////////////////////  // path.comparisons -int path::__compare(const value_type* __s) const { +int path::__compare(string_view_t __s) const {  path_view_iterator thisIter(this->native());  path_view_iterator sIter(__s);  while (!thisIter.is_end() && !sIter.is_end()) { 
diff --git a/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp b/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp index 94de210..61d3225 100644 --- a/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp +++ b/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp 
@@ -28,6 +28,7 @@  #include "test_macros.h"  #include "test_iterators.h"  #include "min_allocator.h" +#include "constexpr_char_traits.hpp"    namespace fs = std::experimental::filesystem;   @@ -59,6 +60,8 @@  using value_type = CharT;  using string_type = std::basic_string<CharT>;  using string_type2 = std::basic_string<CharT, std::char_traits<CharT>, min_allocator<CharT>>; + using string_view_type = std::basic_string_view<CharT>; + using string_view_type2 = std::basic_string_view<CharT, constexpr_char_traits<CharT>>;  using cstr_type = CharT* const;  using const_cstr_type = const CharT*;  using array_type = CharT[25]; @@ -81,6 +84,8 @@  static void Test() {  AssertPathable<string_type>();  AssertPathable<string_type2>(); + AssertPathable<string_view_type>(); + AssertPathable<string_view_type2>();  AssertPathable<cstr_type>();  AssertPathable<const_cstr_type>();  AssertPathable<array_type>(); 
diff --git a/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp index 1118497..93892fb 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp 
@@ -24,6 +24,7 @@    #include <experimental/filesystem>  #include <type_traits> +#include <string_view>  #include <cassert>    #include "test_macros.h" @@ -77,6 +78,7 @@  using namespace fs;  using Ptr = CharT const*;  using Str = std::basic_string<CharT>; + using StrView = std::basic_string_view<CharT>;  using InputIter = input_iterator<Ptr>;    const Ptr L = TC.lhs; @@ -99,6 +101,16 @@  }  assert(LHS == E);  } + // basic_string_view + { + path LHS(L); PathReserve(LHS, ReserveSize); + StrView RHS(R); + { + DisableAllocationGuard g; + LHS /= RHS; + } + assert(LHS == E); + }  // CharT*  {  path LHS(L); PathReserve(LHS, ReserveSize); @@ -153,6 +165,7 @@  using namespace fs;  using Ptr = CharT const*;  using Str = std::basic_string<CharT>; + using StrView = std::basic_string_view<CharT>;  using InputIter = input_iterator<Ptr>;  const Ptr L = TC.lhs;  const Ptr R = TC.rhs; @@ -172,6 +185,21 @@  assert(LHS == E);  assert(&Ref == &LHS);  } + // basic_string_view + { + path LHS(L); + StrView RHS(R); + path& Ref = (LHS /= RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + StrView RHS(R); + path& Ref = LHS.append(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + }  // Char*  {  path LHS(L); 
diff --git a/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp index 4c2d511..ae725a8 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp 
@@ -23,6 +23,7 @@    #include <experimental/filesystem>  #include <type_traits> +#include <string_view>  #include <cassert>    #include "test_macros.h" @@ -69,6 +70,32 @@  assert(p.string<CharT>() == TestPath);  assert(p.string<CharT>() == S);  } + // basic_string<Char, Traits, Alloc> + { + const std::basic_string_view<CharT> S(TestPath); + path p; PathReserve(p, S.length() + 1); + { + // string provides a contigious iterator. No allocation needed. + DisableAllocationGuard g; + path& pref = (p = S); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + assert(p.string<CharT>() == S); + } + { + const std::basic_string_view<CharT> S(TestPath); + path p; PathReserve(p, S.length() + 1); + { + DisableAllocationGuard g; + path& pref = p.assign(S); + assert(&pref == &p); + } + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + assert(p.string<CharT>() == S); + }  //////////////////////////////////////////////////////////////////////////////  // Char* pointers  { 
diff --git a/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp index 557c1b2..64f57f1 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp 
@@ -80,6 +80,7 @@  const path p1(TC.LHS);  const path p2(TC.RHS);  const std::string R(TC.RHS); + const std::string_view RV(TC.RHS);  const int E = TC.expect;  { // compare(...) functions  DisableAllocationGuard g; // none of these operations should allocate @@ -88,7 +89,8 @@  int ret1 = p1.compare(p2);  int ret2 = p1.compare(R);  int ret3 = p1.compare(TC.RHS); - assert(ret1 == ret2 && ret1 == ret3); + int ret4 = p1.compare(RV); + assert(ret1 == ret2 && ret1 == ret3 && ret1 == ret4);  int normalized_ret = ret1 < 0 ? -1 : (ret1 > 0 ? 1 : 0);  assert(normalized_ret == E);   
diff --git a/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp index 6e00afe..cd627b8 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp 
@@ -14,8 +14,9 @@  // class path    // path& operator+=(const path& x); -// path& operator+=(const string_type& x); // Implemented as Source template -// path& operator+=(const value_type* x); // Implemented as Source template +// path& operator+=(const string_type& x); +// path& operator+=(string_view x); +// path& operator+=(const value_type* x);  // path& operator+=(value_type x);  // template <class Source>  // path& operator+=(const Source& x); @@ -29,6 +30,8 @@    #include <experimental/filesystem>  #include <type_traits> +#include <string> +#include <string_view>  #include <cassert>    #include "test_macros.h" @@ -82,6 +85,7 @@  using namespace fs;  using Ptr = CharT const*;  using Str = std::basic_string<CharT>; + using StrView = std::basic_string_view<CharT>;  using InputIter = input_iterator<Ptr>;    const Ptr L = TC.lhs; @@ -98,6 +102,16 @@  }  assert(LHS == E);  } + // basic_string_view + { + path LHS(L); PathReserve(LHS, ReserveSize); + StrView RHS(R); + { + DisableAllocationGuard g; + LHS += RHS; + } + assert(LHS == E); + }  // CharT*  {  path LHS(L); PathReserve(LHS, ReserveSize); @@ -152,6 +166,7 @@  using namespace fs;  using Ptr = CharT const*;  using Str = std::basic_string<CharT>; + using StrView = std::basic_string_view<CharT>;  using InputIter = input_iterator<Ptr>;  const Ptr L = TC.lhs;  const Ptr R = TC.rhs; @@ -171,6 +186,21 @@  assert(LHS == E);  assert(&Ref == &LHS);  } + // basic_string_view + { + path LHS(L); + StrView RHS(R); + path& Ref = (LHS += RHS); + assert(LHS == E); + assert(&Ref == &LHS); + } + { + path LHS(L); + StrView RHS(R); + path& Ref = LHS.concat(RHS); + assert(LHS == E); + assert(&Ref == &LHS); + }  // Char*  {  path LHS(L); @@ -246,6 +276,13 @@  assert(LHS == (const char*)TC.expect);  assert(&Ref == &LHS);  } + { + path LHS((const char*)TC.lhs); + std::string_view RHS((const char*)TC.rhs); + path& Ref = (LHS += RHS); + assert(LHS == (const char*)TC.expect); + assert(&Ref == &LHS); + }  doConcatSourceTest<char> (TC);  doConcatSourceTest<wchar_t> (TC);  doConcatSourceTest<char16_t>(TC); @@ -265,6 +302,18 @@  }  assert(LHS == E);  } + { + path LHS((const char*)TC.lhs); + std::string_view RHS((const char*)TC.rhs); + const char* E = TC.expect; + PathReserve(LHS, StrLen(E) + 5); + { + DisableAllocationGuard g; + path& Ref = (LHS += RHS); + assert(&Ref == &LHS); + } + assert(LHS == E); + }  doConcatSourceAllocTest<char>(TC);  doConcatSourceAllocTest<wchar_t>(TC);  } 
diff --git a/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp b/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp index d89e7c8..402225d 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp +++ b/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp 
@@ -47,6 +47,13 @@  assert(p.string<CharT>() == TestPath);  assert(p.string<CharT>() == S);  } + { + const std::basic_string_view<CharT> S(TestPath); + path p(S); + assert(p.native() == Expect); + assert(p.string<CharT>() == TestPath); + assert(p.string<CharT>() == S); + }  // Char* pointers  {  path p(TestPath); 
diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html index 57a7505..9ce2e00 100644 --- a/www/cxx1z_status.html +++ b/www/cxx1z_status.html 
@@ -118,7 +118,7 @@ 	<tr><td><a href="http://wg21.link/p0346r1">p0346r1</a></td><td>LWG</td><td>A &lt;random&gt; Nomenclature Tweak</td><td>Oulu</td><td></td><td></td></tr> 	<tr><td><a href="http://wg21.link/p0358r1">p0358r1</a></td><td>LWG</td><td>Fixes for not_fn</td><td>Oulu</td><td>Complete</td><td>3.9</td></tr> 	<tr><td><a href="http://wg21.link/p0371r1">p0371r1</a></td><td>LWG</td><td>Temporarily discourage memory_order_consume</td><td>Oulu</td><td></td><td></td></tr> -	<tr><td><a href="http://wg21.link/p0392r0">p0392r0</a></td><td>LWG</td><td>Adapting string_view by filesystem paths</td><td>Oulu</td><td></td><td></td></tr> +	<tr><td><a href="http://wg21.link/p0392r0">p0392r0</a></td><td>LWG</td><td>Adapting string_view by filesystem paths</td><td>Oulu</td><td>Complete</td><td>4.0</td></tr> 	<tr><td><a href="http://wg21.link/p0393r3">p0393r3</a></td><td>LWG</td><td>Making Variant Greater Equal</td><td>Oulu</td><td></td><td></td></tr> 	<tr><td><a href="http://wg21.link/P0394r4">P0394r4</a></td><td>LWG</td><td>Hotel Parallelifornia: terminate() for Parallel Algorithms Exception Handling</td><td>Oulu</td><td></td><td></td></tr>  <!--	<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr> -->